import java.net.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.io.*;

public class Server  {
    private ServerSocket accepter;
    private Socket clientSocket;
    private ChatQueue chatqueue;
    private GameQueue gamequeue;
    private ChatPanel panel;
    
    private ArrayBlockingQueue<Integer> IDQueue;
    
    private AccepterThread accepterthread;
    private MessageThread messagethread;
    private GameThread gamethread;
    
    public Server(ChatPanel panel) {
        this.panel = panel;
        
        chatqueue = new ChatQueue();
        gamequeue = new GameQueue();
        
        IDQueue = new ArrayBlockingQueue<Integer>(1000000);
        IDThread IDS = new IDThread();
        IDS.start();
        
        try {
                accepter = new ServerSocket(8888);
                
                accepterthread = new AccepterThread();
                accepterthread.start();
                
                messagethread = new MessageThread();
                messagethread.start();
                
                gamethread = new GameThread();
                gamethread.start();
                
        } catch (IOException e) { 
        	System.out.println("Server IO");
                System.out.println("IOException " + e); 
        }
    
    }
    
    public void connectTo(String ip)
    {
        HandShaker hs = new HandShaker(ip,panel.username);
        hs.start();
    }
    
    public void sendUsers(String name, String ip)
    {
        (new HandShaker(ip,name,panel)).start();
    }
    
    private class AccepterThread extends Thread { 
            public void run() {
                        while (true) {
                                try { 
                                    clientSocket = accepter.accept();
                                    DirectorThread director = new DirectorThread(clientSocket, chatqueue, gamequeue, panel);
                                    director.start();
                                } catch(IOException e) { 
                                        System.out.println("IOException: " + e);
                                }
                        }
            }
    
    }
    
    private class MessageThread extends Thread { 
        public void run() { 
            while (true) { 
                    if(chatqueue.hasMessage()) { 
                            ChatQueue.Packet p = chatqueue.getMessage();
                            if(p.id == 0)
                                    sendUsers(p.username, p.msg);
                            else if(p.id == 1)
                                    panel.addIP(p.msg, p.username);
                            else if(p.id == 2)
                                    panel.receiveLogoff(p.username);
                            else if(p.id == 3)
                                    panel.receivePoke(p.username);
                            else if(p.id == 4)
                                    panel.receiveMessage(p.username, p.msg);
                            else if(p.id == 5)
                                    panel.receiveWhisper(p.username, p.msg);
                    }
            }
        }
    }
    
    private class GameThread extends Thread { 
    	public void run() { 
    		while(true) { 
    			if(gamequeue.hasUpdate()) { 
    				GameQueue.Update u = gamequeue.getMessage();
    				if(u.id == 7) { 
    					u.id = IDQueue.poll();
    					//handshake and send unique id to both
    					u.board = panel.game.connectGame(u.id, u.username);
    				}
    				panel.game.playerMoved(u.id, u.username, u.board);
    			}
    		}
    	}
    }
    
    public class IDThread extends Thread { 
    	public void run() { 
    		int i = 8;
    		while(true) { 
    			if(IDQueue.offer(i))
    				i++;
    		}
    	}
    }

}